function distanceSq(ax, ay, bx, by) {
  const dx = ax - bx
  const dy = ay - by
  return dx * dx + dy * dy
}
function distanceSq3D(ax, ay, az, bx, by, bz) {
  const dx = ax - bx
  const dy = ay - by
  const dz = az - bz
  return dx * dx + dy * dy + dz * dz
}
// Given point B and segment AC, return the squared distance from B to the
// nearest point on AC
// Receive the squared length of segments AB, BC, AC
// TODO: analyze rounding error. Returns 0 for these coordinates:
//    P: [2, 3 - 1e-8]  AB: [[1, 3], [3, 3]]
//
function apexDistSq(ab2, bc2, ac2) {
  let dist2 = null
  if (ac2 === 0) {
    dist2 = ab2
  } else if (ab2 >= bc2 + ac2) {
    dist2 = bc2
  } else if (bc2 >= ab2 + ac2) {
    dist2 = ab2
  } else {
    const dval = (ab2 + ac2 - bc2)
    dist2 = ab2 -  dval * dval / ac2  * 0.25
  }
  if (dist2 < 0) {
    dist2 = 0
  }
  return dist2
}
function pointSegDistSq(ax, ay, bx, by, cx, cy) {
  const ab2 = distanceSq(ax, ay, bx, by)
  const ac2 = distanceSq(ax, ay, cx, cy)
  const bc2 = distanceSq(bx, by, cx, cy)
  return apexDistSq(ab2, ac2, bc2)
}
function pointSegDistSq3D(ax, ay, az, bx, by, bz, cx, cy, cz) {
  const ab2 = distanceSq3D(ax, ay, az, bx, by, bz)
  const ac2 = distanceSq3D(ax, ay, az, cx, cy, cz)
  const bc2 = distanceSq3D(bx, by, bz, cx, cy, cz)
  return apexDistSq(ab2, ac2, bc2)
}
function calcArcBounds(xx, yy, start, len) {
  let i = start | 0
  const n = isNaN(len) ? xx.length - i : len + i
  let x, y, xmin, ymin, xmax, ymax
  if (n > 0) {
    xmin = xmax = xx[i]
    ymin = ymax = yy[i]
  }
  for (i++; i < n; i++) {
    x = xx[i]
    y = yy[i]
    if (x < xmin) xmin = x
    if (x > xmax) xmax = x
    if (y < ymin) ymin = y
    if (y > ymax) ymax = y
  }
  return [xmin, ymin, xmax, ymax]
}
function containsBounds(a, b) {
  return a[0] <= b[0] && a[2] >= b[2] && a[1] <= b[1] && a[3] >= b[3]
}
export default {
  pointSegDistSq,
  pointSegDistSq3D,
  calcArcBounds,
  containsBounds,
}